#ifndef UTILITY_HPP
#define UTILITY_HPP

#include <QString>
#include <QDateTime>
#include <QStringList>
#include <QDebug>

/**
 * @brief 时间单位枚举
 */
enum TimeUnit {
    Seconds, ///< 秒
    Minutes, ///< 分钟
    Hours,   ///< 小时
    Days     ///< 天
};

/**
 * 定义一个结构体来表示时间差异，包括天数、小时、分钟、秒和毫秒。
 */
struct TimeDifference {
    qint64 days;          // 天数差异
    int hours;            // 小时差异
    int minutes;          // 分钟差异
    int seconds;          // 秒差异
    int milliseconds;     // 毫秒差异
};

/**
 * @brief 解析类型字符串为整数。
 *
 * 将 "input"、"output"、"servo" 分别解析为 0、1、2。未知类型返回 -1。
 *
 * @param typeStr 类型字符串（例如 "input"）
 * @return int 对应的整数值或 -1 表示未知类型
 *
 * @code
 * int type = parseType("output"); // type = 1
 * int invalidType = parseType("unknown"); // invalidType = -1
 * @endcode
 */
inline int parseType(const char* typeStr) {
    if (!typeStr) return -1;
    QString t = QString::fromUtf8(typeStr).toLower();
    if (t == "input") return 0;
    else if (t == "output") return 1;
    else if (t == "servo")  return 2;
    return -1; // 未知类型
}

/**
 * @brief 解析值字符串为整数（True/False）。
 *
 * 将 "true" 解析为 0，"false" 解析为 1。未知值返回 -1。
 *
 * @param valueStr 值字符串（例如 "true"）
 * @return int 对应的整数值或 -1 表示未知值
 *
 * @code
 * int valTrue = parseValue("true");   // valTrue = 0
 * int valFalse = parseValue("false"); // valFalse = 1
 * int valUnknown = parseValue("maybe"); // valUnknown = -1
 * @endcode
 */
inline int parseValue(const char* valueStr) {
    if (!valueStr) return -1;
    QString v = QString::fromUtf8(valueStr).toLower();
    if (v == "true")  return 1;
    if (v == "false") return 0;
    return -1; // 未知值
}

/**
 * @brief 从文件夹名中解析日期。
 *
 * 例如 "01#2024-12-13" 解析为 QDateTime(2024-12-13 00:00:00)。
 *
 * @param folderName 文件夹名称
 * @return QDateTime 解析后的日期时间，如果解析失败则返回无效的 QDateTime
 *
 * @code
 * QDateTime dateTime = parseFolderDate("01#2024-12-13");
 * // dateTime 代表 2024-12-13 00:00:00
 *
 * QDateTime invalidDate = parseFolderDate("invalid_folder");
 * // invalidDate.isValid() == false
 * @endcode
 */
inline QDateTime parseFolderDate(const QString &folderName) {
    QStringList parts = folderName.split('#');
    if (parts.size() < 2) {
        return QDateTime();
    }
    QString dateStr = parts.last();
    QDate date = QDate::fromString(dateStr, "yyyy-MM-dd");
    if (!date.isValid()) {
        return QDateTime();
    }
    return QDateTime(date, QTime(0,0,0));
}

/**
 * @brief 从文件名中提取文件号。
 *
 * 例如 "14.xml" 提取为 14。
 *
 * @param fileName 文件名
 * @return int 文件号或 -1 表示无效
 *
 * @code
 * int fileNumber = parseFileNumber("14.xml"); // fileNumber = 14
 * int invalidNumber = parseFileNumber("invalid.xml"); // invalidNumber = -1
 * @endcode
 */
inline int parseFileNumber(const QString &fileName) {
    QString base = fileName;
    if (base.endsWith(".xml", Qt::CaseInsensitive)) {
        base.chop(4); // 移除后缀 ".xml"
    }
    bool ok = false;
    int num = base.toInt(&ok);
    return ok ? num : -1;
}

/**
 * @brief 计算两个 QDateTime 之间的时间差。
 *
 * 可以选择以秒、分钟、小时或天为单位返回时间差。
 *
 * @param startTime 开始时间
 * @param endTime 结束时间
 * @param unit 时间差的单位，默认为秒（Seconds）
 * @return double 返回时间差，单位由参数 unit 决定。如果时间无效则返回 -1.0
 *
 * @code
 * QDateTime startTime = QDateTime::fromString("2024-12-01T10:00:00", Qt::ISODate);
 * QDateTime endTime = QDateTime::fromString("2024-12-01T12:30:00", Qt::ISODate);
 *
 * double diffSeconds = calculateTimeDifference(startTime, endTime, Seconds); // 9000.0
 * double diffMinutes = calculateTimeDifference(startTime, endTime, Minutes); // 150.0
 * double diffHours = calculateTimeDifference(startTime, endTime, Hours);     // 2.5
 * double diffDays = calculateTimeDifference(startTime, endTime, Days);       // 0.104166...
 * @endcode
 */
inline double calculateTimeDifference(const QDateTime& startTime, const QDateTime& endTime, TimeUnit unit = Seconds) {
    if (!startTime.isValid() || !endTime.isValid()) {
        qWarning() << "Invalid QDateTime values.";
        return -1.0;
    }

    qint64 diffInMilliseconds = startTime.msecsTo(endTime);

    switch (unit) {
    case Seconds:
        return diffInMilliseconds / 1000.0;
    case Minutes:
        return diffInMilliseconds / (1000.0 * 60);
    case Hours:
        return diffInMilliseconds / (1000.0 * 60 * 60);
    case Days:
        return diffInMilliseconds / (1000.0 * 60 * 60 * 24);
    default:
        return diffInMilliseconds / 1000.0;  // 默认返回秒
    }
}

/**
 * @brief 计算两个时间差的字符串表示。
 *
 * 可以选择以秒、分钟、小时或天为单位返回格式化的时间差字符串。
 *
 * @param startTime 开始时间
 * @param endTime 结束时间
 * @param unit 时间差的单位，默认为秒（Seconds）
 * @return QString 返回格式化的时间差字符串。如果时间无效则返回 "Invalid Time"
 *
 * @code
 * QDateTime startTime = QDateTime::fromString("2024-12-01T10:00:00", Qt::ISODate);
 * QDateTime endTime = QDateTime::fromString("2024-12-01T12:30:00", Qt::ISODate);
 *
 * QString diffStrSeconds = formatTimeDifference(startTime, endTime, Seconds); // "9000.00 seconds"
 * QString diffStrHours = formatTimeDifference(startTime, endTime, Hours);     // "2.50 hours"
 * QString invalidDiff = formatTimeDifference(startTime, QDateTime(), Seconds); // "Invalid Time"
 * @endcode
 */
inline QString formatTimeDifference(const QDateTime& startTime, const QDateTime& endTime, TimeUnit unit = Seconds) {
    double diff = calculateTimeDifference(startTime, endTime, unit);
    if (diff < 0) {
        return "Invalid Time";
    }

    switch (unit) {
    case Seconds:
        return QString::number(diff, 'f', 2) + " seconds";
    case Minutes:
        return QString::number(diff, 'f', 2) + " minutes";
    case Hours:
        return QString::number(diff, 'f', 2) + " hours";
    case Days:
        return QString::number(diff, 'f', 2) + " days";
    default:
        return QString::number(diff, 'f', 2) + " seconds";
    }
}


/**
 * 示例代码：
 * 计算两个 QDateTime 对象之间的时间差异，并输出天数、小时、分钟、秒和毫秒的差异。
 * QDateTime startDateTime(QDate(2024, 4, 25), QTime(14, 30));
 * QDateTime endDateTime(QDate(2024, 4, 26), QTime(16, 45));
 * QDateTime duration = QDateTime(QDate(2024, 12, 20), QTime(14, 23, 10, 66));
 * QDateTime diff = timeDifference(startDateTime, endDateTime);
 * QDateTime diffDuration = timeDifference(startDateTime, duration);
 *
 * TimeDifference diffTime = calculateFullTimeDifference(diff, diffDuration);
 * qDebug() << "天数差异:" << diffTime.days;
 * qDebug() << "小时差异:" << diffTime.hours;
 * qDebug() << "分钟差异:" << diffTime.minutes;
 * qDebug() << "秒差异:" << diffTime.seconds;
 * qDebug() << "毫秒差异:" << diffTime.milliseconds;
 */

inline QDateTime timeDifference(const QDateTime &startDateTime, const QDateTime &endDateTime) {
    qDebug() << startDateTime << endDateTime;

    // 提取开始和结束时间的时间部分（忽略日期）
    QTime queryStartTime = startDateTime.time();
    QTime queryEndTime = endDateTime.time();

    // 输出调试信息
    qDebug() << "Start Time:" << queryStartTime.toString("HH:mm:ss.zzz");
    qDebug() << "End Time:" << queryEndTime.toString("HH:mm:ss.zzz");

    // 检查时间是否相等
    if (queryStartTime == queryEndTime) {
        qDebug() << "Times are equal. Returning zero difference.";
        QDate currentDate = QDate::currentDate();
        return QDateTime(currentDate, QTime(0, 0, 0, 0));
    }

    // 计算时间差，单位为毫秒
    int diffMilliseconds = queryStartTime.msecsTo(queryEndTime);

    // 输出差异毫秒数
    qDebug() << "Difference in milliseconds:" << diffMilliseconds;

    // 如果差异为负，则设置为0，避免负值
    if (diffMilliseconds < 0) {
        qWarning() << "End time is earlier than start time. Setting difference to 0.";
        diffMilliseconds = 0;
    }

    // 获取当前日期
    QDate currentDate = QDate::currentDate();

    // 创建一个新的 QDateTime 对象，使用当前日期和零点时间
    QDateTime resultDateTime(currentDate, QTime(0, 0, 0, 0));

    // 添加总毫秒数
    resultDateTime = resultDateTime.addMSecs(diffMilliseconds);

    // 输出结果调试信息
    qDebug() << "Result Time:" << resultDateTime.toString("yyyy-MM-dd HH:mm:ss.zzz");

    return resultDateTime;
}

/**
 * 示例代码：
 * 计算两个 QDateTime 对象之间的完整时间差异，并输出各个时间单位的差异。
 *
 * QDateTime start(QDate(2024, 4, 25), QTime(14, 30));
 * QDateTime end(QDate(2024, 4, 26), QTime(16, 45));
 * TimeDifference diff = calculateFullTimeDifference(start, end);
 *
 * qDebug() << "天数差异:" << diff.days;
 * qDebug() << "小时差异:" << diff.hours;
 * qDebug() << "分钟差异:" << diff.minutes;
 * qDebug() << "秒差异:" << diff.seconds;
 * qDebug() << "毫秒差异:" << diff.milliseconds;
 */

inline TimeDifference calculateFullTimeDifference(const QDateTime &startDateTime, const QDateTime &endDateTime) {
    // 计算两个 QDateTime 之间的总毫秒差异
    qint64 totalMilliseconds = startDateTime.msecsTo(endDateTime);

    bool isNegative = false; // 标记时间差是否为负数
    if (totalMilliseconds < 0) {
        isNegative = true;
        totalMilliseconds = -totalMilliseconds; // 取绝对值以便后续计算
    }

    TimeDifference diff; // 创建一个 TimeDifference 结构体实例

    // 计算天数差异
    diff.days = totalMilliseconds / (1000 * 60 * 60 * 24);
    totalMilliseconds %= (1000 * 60 * 60 * 24); // 剩余毫秒

    // 计算小时差异
    diff.hours = totalMilliseconds / (1000 * 60 * 60);
    totalMilliseconds %= (1000 * 60 * 60); // 剩余毫秒

    // 计算分钟差异
    diff.minutes = totalMilliseconds / (1000 * 60);
    totalMilliseconds %= (1000 * 60); // 剩余毫秒

    // 计算秒差异
    diff.seconds = totalMilliseconds / 1000;
    // 计算毫秒差异
    diff.milliseconds = totalMilliseconds % 1000;

    if (isNegative) {
        // 根据需要处理负差异，例如添加一个标志或转换为负数
        // 例如，可以在结构体中添加一个 isNegative 字段来表示时间差的方向
        // 当前实现中未对负差异进行进一步处理
    }

    return diff; // 返回填充好的 TimeDifference 结构体
}



inline bool isWithinRange(const QDateTime& start, const QDateTime& end, const QDateTime& compare) {
    // 确保 start 是早于 end
    QDateTime actualStart = start < end ? start : end;
    QDateTime actualEnd = start < end ? end : start;

    // 判断 compare 是否在 [actualStart, actualEnd] 之间
    return (compare >= actualStart) && (compare <= actualEnd);
}

#endif // UTILITY_HPP
